<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="result"></div>
<script>
    /**
     * 对于前端来说 Worker 指的就是 Web Worker。
     *
     * 当在 HTML 页面中执行脚本时，页面的状态是不可响应的，直到脚本已完成。
     * Web Worker 是运行在后台的 JavaScript，独立于其他脚本，不会影响页面的性能。
     * 您可以继续做任何愿意做的事情：点击、选取内容等等，而此时 Web Worker 在后台运行。
     *
     * */

    /**
     * 1. 创建一个单独 js 文件，假如就叫做 demo-worker.js
     * */
    /**
     * 2. 创建 Worker 实例
     * const worker = new Worker(path, options);
     *
     * 2.1 path: 有效的js脚本的地址，必须遵守同源策略。无效的js地址或者违反同源策略，会抛出SECURITY_ERR 类型错误
     * 2.2 options.type 可选，用以指定 worker 类型。该值可以是 classic 或 module。 如未指定，将使用默认值 classic
     * 2.3 options.credentials 可选，用以指定 worker 凭证。该值可以是 omit, same-origin，或 include。如果未指定，或者 type 是 classic，将使用默认值 omit (不要求凭证)
     * 2.4 options.name 可选，在 DedicatedWorkerGlobalScope 的情况下，用来表示 worker 的 scope 的一个 DOMString 值，主要用于调试目的。
     *
     * */
    function startWorker() {
        if (typeof Worker !== "undefined") {
            let count = 0;
            const myWorker = new Worker("demo-worker.js");

            /**
             * 1. 主线程接受 worker 线程发来的消息
             * */
            myWorker.addEventListener("message", function (event) {
                console.log(event);
                count = event.data
                document.getElementById("result").innerHTML = count;

                /**
                 * 2. 主线程向 worker 线程发送消息
                 *
                 * 主线程与 worker 线程之间的数据传递是深拷贝，是传值而不是传地址。
                 *
                 * */
                if (count >= 10) {
                    const obj = { type: 'done' }
                    myWorker.postMessage(obj)

                    /**
                     * 4. 在主线程中关闭 worker 线程
                     *
                     * 4.1 在主线程和 worker 线程中都可以关闭 worker 线程
                     * 4.2 在主线程关闭 worker，主线程与 worker 线程之间的连接都会被立刻停止。即使 worker 线程当前的 Event Loop 中仍有待执行的任务继续调用 postMessage() 方法，但主线程不会再接收到消息。
                     * 4.3 在 worker 线程中关闭 worker，不会直接断开与主线程的连接，而是等 worker 线程当前的 Event Loop 所有任务执行完，再关闭。也就是说，在当前 Event Loop 中继续调用 postMessage() 方法，主线程还是能通过监听message事件收到消息。
                     *
                     * */
                    myWorker.terminate();
                }
            })
            // 或者
            // myWorker.onmessage = function (event) {
            //     document.getElementById("result").innerHTML = event.data;
            // };

            /**
             * 3. 主线程监听错误消息
             *
             * 3.1 error 当worker内部出现错误时触发
             * 3.2 messageerror 当 message 事件接收到无法被反序列化的参数时触发
             *
             * */
            myWorker.addEventListener('error', (e) => {
                console.log(e.message);
            })
            myWorker.addEventListener('messageerror', (e) => {
                console.log(e.message);
            })

        } else {
            document.getElementById("result").innerHTML = "抱歉，你的浏览器不支持 Web Workers...";
        }
    }

    startWorker()


</script>
</body>
</html>